﻿using System;

using zijian666.Abstractions;

namespace zijian666.Translator;

/// <summary>
/// <see cref="IConvertible"/>对象的翻译器
/// </summary>
public class IConvertibleTranslator : ITranslator
{
    /// <inheritdoc />
    public bool TryTranslate(IConvertContext context, object? input, out object? translated)
    {
        if (input is not IConvertible convertible)
        {
            translated = null;
            return false;
        }
        translated = convertible.GetTypeCode() switch
        {
            TypeCode.Boolean when input is not bool => convertible.ToBoolean(context.Settings.CultureInfo),
            TypeCode.Byte when input is not byte => convertible.ToByte(context.Settings.CultureInfo),
            TypeCode.Char when input is not char => convertible.ToChar(context.Settings.CultureInfo),
            TypeCode.DateTime when input is not DateTime => convertible.ToDateTime(context.Settings.CultureInfo),
            TypeCode.Decimal when input is not decimal => convertible.ToDecimal(context.Settings.CultureInfo),
            TypeCode.Double when input is not double => convertible.ToDouble(context.Settings.CultureInfo),
            TypeCode.Int16 when input is not short => convertible.ToInt16(context.Settings.CultureInfo),
            TypeCode.Int32 when input is not int => convertible.ToInt32(context.Settings.CultureInfo),
            TypeCode.Int64 when input is not long => convertible.ToInt64(context.Settings.CultureInfo),
            TypeCode.SByte when input is not sbyte => convertible.ToSByte(context.Settings.CultureInfo),
            TypeCode.Single when input is not float => convertible.ToSingle(context.Settings.CultureInfo),
            TypeCode.UInt16 when input is not ushort => convertible.ToUInt16(context.Settings.CultureInfo),
            TypeCode.UInt32 when input is not uint => convertible.ToUInt32(context.Settings.CultureInfo),
            TypeCode.UInt64 when input is not ulong => convertible.ToUInt64(context.Settings.CultureInfo),
            TypeCode.DBNull when input is not DBNull => DBNull.Value,
            TypeCode.String when input is not string => convertible.ToString(context.Settings.CultureInfo),
            TypeCode.Object => convertible.ToType(typeof(object), context.Settings.CultureInfo),
            TypeCode.Empty => null,
            _ => input,
        };
        return !ReferenceEquals(translated, convertible);
    }
}
